<?php
namespace Iaem\UserBundle\Security\Core\User;

use FOS\UserBundle\Model\UserManagerInterface;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class FOSUBUserProvider extends BaseClass
{

    /** @var $encoderFactory EncoderFactoryInterface */
    protected $encoderFactory;

    /**
     * @param mixed $encoderFactory
     * @return FOSUBUserProvider
     */
    public function setEncoderFactory(EncoderFactoryInterface $encoderFactory)
    {
        $this->encoderFactory = $encoderFactory;
        return $this;
    }

    /**
    * {@inheritDoc}
    */
    public function connect(UserInterface $user, UserResponseInterface $response) {
        $property = $this->getProperty($response);
        $username = $response->getUsername();

        $service = $response->getResourceOwner()->getName();

        $setter = 'set' . ucfirst($service);
        $setter_id = $setter . 'Id';
        $setter_token = $setter . 'AccessToken';

        if (null !== $previousUser = $this->userManager->findUserBy(array($property => $username))) {
            $previousUser->$setter_id(null);
            $previousUser->$setter_token(null);
            $this->userManager->updateUser($previousUser);
        }

        $user->$setter_id($username);
        $user->$setter_token($response->getAccessToken());

        $this->userManager->updateUser($user);
    }
    /**
     * {@inheritdoc}
     */
    public function loadUserByOAuthUserResponse(UserResponseInterface $response)
    {
        // @TODO  При текушей схеме авторизации есть важный нюанс!
        // Если мы первый раз зашли с google, а потом пытаемся зайти с facebook
        // То пользователя все равно авторизует как с google (потому-что могут совпадать e-mail)
        // Если мы первый раз зашли с facebook, а потом пытаемся зайти с twitter
        // То пользователя все равно авторизует как с facebook (потому-что могут совпадать username)

        $username = $response->getUsername();

        $user = $this->userManager->findUserBy(array($this->getProperty($response) => $username));

        if (null === $user && $response->getEmail()) {
            $user = $this->userManager->findUserByEmail($response->getEmail());
        }

        if (null === $user && $response->getResourceOwner()->getName() != 'google' && $response->getNickname()) {
            $user = $this->userManager->findUserByUsername($response->getNickname());
        }

        if (null === $user) {
            $service = $response->getResourceOwner()->getName();
            $setter = 'set'.ucfirst($service);
            $setter_id = $setter.'Id';
            $setter_token = $setter.'AccessToken';
            $user = $this->userManager->createUser();
            $user->$setter_id($username);
            $user->$setter_token($response->getAccessToken());

            if ($response->getEmail()) {
                $user->setUsername($response->getEmail());
                $user->setEmail($response->getEmail());
            } else {
                $user->setUsername($response->getUsername());
                $user->setEmail($response->getUsername());
            }

            if ($service == 'twitter' || $service == 'google' || $service == 'facebook') {
                if (($service != 'google') && $response->getNickname()) {
                    $user->setUsername($response->getNickname());
                }
                $user->setFirstName(explode(' ', $response->getRealname())[0]);
                $user->setLastName(explode(' ', $response->getRealname())[1]);
            }

            if ($service == 'vkontakte') {
               if ($response->getNickname()) $user->setUsername($response->getNickname());
                $user->setFirstName($response->getResponse()['response'][0]['first_name']);
                $user->setLastName($response->getResponse()['response'][0]['last_name']);
            }

            if ($service == 'odnoklassniki') {
                if ($response->getNickname()) $user->setUsername($response->getNickname());
                $user->setFirstName($response->getResponse()['first_name']);
                $user->setLastName($response->getResponse()['last_name']);
            }

            $password = $this->encoderFactory
                ->getEncoder($user)
                ->encodePassword($username, $user->getSalt());

            $user->setPassword($password);
            $user->setEnabled(true);
            $this->userManager->updateUser($user);
            return $user;
        }

        return $user;
    }

}
